home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_200 / 283_03 / macros.c < prev    next >
C/C++ Source or Header  |  1988-12-01  |  8KB  |  387 lines

  1.  
  2. /* macros.c -- 11/27/88, d.c.oshel */
  3.  
  4. #include <stdarg.h>
  5. #include "burlap.h"
  6.  
  7. extern FORM_RULES burlap[];
  8.  
  9. static char *token;
  10. static char *slop;
  11. static char *moreslop;
  12.  
  13.  
  14. jmp_buf osiris;
  15.  
  16.  
  17. static int crash_macro( char *msg,... )
  18. {
  19.     va_list arg_ptr;
  20.     char buffer[128];
  21.  
  22.     va_start( arg_ptr, msg );
  23.     vsprintf( buffer, msg, arg_ptr );
  24.     va_end( arg_ptr );
  25.  
  26.     boxmsg( buffer );
  27.     longjmp( osiris,-1 );
  28. }
  29.  
  30.  
  31. static int valid_number( char *p )
  32. {
  33.     static char test[] = "0123456789-.,$+";
  34.  
  35.     for ( ; *p; p++ )
  36.     {
  37.         if ( strchr( test, *p ) == NULL )
  38.             return (0);
  39.     }
  40.     return (1);
  41. }
  42.  
  43.  
  44. static int numeric_args( char * a1, char * a2 )
  45. {
  46.     return ( valid_number( a1 ) && valid_number( a2 ) );
  47. }
  48.  
  49.  
  50. static long number( char *p )
  51. {
  52.     long n, sign;
  53.  
  54.     for ( n = 0L, sign = 1L; *p; p++ )
  55.     {
  56.         if ( *p == '-' )
  57.             sign = -1L;
  58.         else if ( isdigit(*p) )
  59.         {
  60.             n *= 10L;
  61.             n += (long) (*p - '0');
  62.         }
  63.     }
  64.     n *= sign;
  65.     return ( n );    
  66. }
  67.  
  68.  
  69. /* load_and_compare() --
  70.  
  71.    this function determines N from the first field in q,
  72.    then moves the contents of field N to token,
  73.    then move the string argument which immediately follows in q to moreslop,
  74.    then returns the result of case-insensitive comparison between the two
  75.    */
  76.  
  77. static int load_and_compare( char *q, char *op )
  78. {
  79.     int k, j, n, len;
  80.     char *p;
  81.  
  82.     memset(token,0,MACROSIZE);
  83.     memset(moreslop,0,MACROSIZE);
  84.  
  85.     /* numeric argument refers to a burlap field */
  86.     if (*q)
  87.     {
  88.         for( ; *q && !(isdigit(*q) || *q == '-'); q++ )
  89.         ;
  90.         for ( n = 0; *q && (isdigit(*q) || *q == '-'); q++ )
  91.         {
  92.             if (*q == '-')
  93.                 ;
  94.             else
  95.             {
  96.                 n *= 10;
  97.                 n += (*q - '0');
  98.             }
  99.         }
  100.  
  101.         /* index array on base 0, and do range check */
  102.         n -= 1; 
  103.         if ( n < 0 || n > ISAM_field_range )  /* 0 <= n <= NUMBER_OF_REAL_FIELDS */
  104.             n = ISAM_field_range;
  105.  
  106.         len = burlap[n].len;
  107.         if (len < 0)
  108.             len = MAXVFLDLEN;
  109.         p = *(burlap[n].fptr);
  110.         memcpy( token, p, len );
  111.         strip_blanks( token );
  112.         strlwr(token);
  113.     }
  114.  
  115.     /* string argument might be quoted */
  116.     if (*q)
  117.     {
  118.         for( ++q; *q && *q == ' '; q++ )
  119.         ;
  120.         if (*q)
  121.         {
  122.             if (*q == APOSTROPHE || *q == QUOTE)
  123.                 k = *q++; /* delimiter */
  124.             else
  125.                 k = EOL;
  126.  
  127.             for ( j = 0; *q && *q != k; q++, j++ )
  128.                 *(moreslop + j) = *q;
  129.             strip_blanks( moreslop );
  130.             strlwr( moreslop );
  131.         }
  132.     }
  133.     
  134.     return (strcmp( token, moreslop ));
  135. }
  136.  
  137.  
  138. /*======================  Recursive Macro Expansions  ======================*/
  139.  
  140. int expand_macros( char *buffer )
  141. {
  142.     char *p, *q;        /* RECURSIVE */
  143.     char /* **r, *str, */ *tkn;
  144.  
  145.     static int i, arg1, arg2, sign;
  146.  
  147.     /* RECURSIVE, but macros expand by inserting in place, so the
  148.        receiving buffer is not adversely affected by nested macros, 
  149.        and there is NO undue stress on the stack!  There is no
  150.        error checking, but the working buffers are huge, so there is
  151.        no problem with almost any practical expansion.
  152.        
  153.        In the burlap version, all of the defined macros "expand" to 
  154.        shorter, not longer, strings.
  155.        */
  156.  
  157.  
  158.     if ( (p = strstr( buffer, "(" )) != NULL )
  159.     {
  160.         if ( strstr( p + 1, "(" ) != NULL )
  161.         {
  162.             expand_macros( p + 1 ); /* RECURSIVE */
  163.         }
  164.  
  165.         q = p;    /* mark opening paren */
  166.  
  167.         i = 0;
  168.         while (*p)
  169.         {
  170.             if (*p == '(')  /* skip over "quoted macros" embedded in arg */
  171.                 ++i;
  172.             else if (*p == ')')
  173.                 --i;
  174.  
  175.             if ( !i )
  176.                 break;
  177.             else
  178.                 p++;
  179.         }
  180.  
  181.         if ( *p != ')' )
  182.             crash_macro("macro needs ')': %s", q );
  183.  
  184.         *q = '\0';  /* wipes out opening paren */
  185.         *p = '\0';  /* wipes out closing paren and delimits macro */
  186.         ++p;        /* advance beyond macro to next portion of buffer */
  187.  
  188.         /* ===== Arithmetic and Logical Operators ===== */
  189.  
  190.         if ((i = *( q + 1 )) == '&' || 
  191.                   i == '|' ||
  192.                   i == '^'
  193.                 )
  194.         {
  195.             tkn = q + 1;
  196.             for( q += 2; *q && !(isdigit(*q) || *q == '-'); q++ )
  197.             ;
  198.             for ( sign = 1, arg1 = 0; *q && (isdigit(*q) || *q == '-'); q++ )
  199.             {
  200.                 if (*q == '-')
  201.                     sign = -1;
  202.                 else
  203.                 {
  204.                     arg1 *= 10;
  205.                     arg1 += (*q - '0');
  206.                 }
  207.             }
  208.             arg1 *= sign;
  209.             for( ++q; *q && !(isdigit(*q) || *q == '-'); q++ )
  210.             ;
  211.             for ( sign = 1, arg2 = 0; *q && (isdigit(*q) || *q == '-'); q++ )
  212.             {
  213.                 if (*q == '-')
  214.                     sign = -1;
  215.                 else
  216.                 {
  217.                     arg2 *= 10;
  218.                     arg2 += (*q - '0');
  219.                 }
  220.             }
  221.             arg2 *= sign;
  222.             switch (i)
  223.             {
  224.             case '&': arg1 = (arg1 != 0)? 1: 0;
  225.                       arg2 = (arg2 != 0)? 1: 0;
  226.                       arg1 &= arg2;
  227.                       break;
  228.             case '|': arg1 = (arg1 != 0)? 1: 0;
  229.                       arg2 = (arg2 != 0)? 1: 0;
  230.                       arg1 |= arg2;
  231.                       break;
  232.             case '^': arg1 = (arg1 != 0)? 1: 0;
  233.                       arg1 ^= 1;
  234.                       break;
  235.             }
  236.             sprintf( slop, "%d", arg1 );
  237.         }
  238.  
  239.         /* ===== Conditionals ===== */
  240.  
  241.         else if ( strncmp( q + 1, "<=", 2 ) == 0 )
  242.         {
  243.             i = load_and_compare(q+1,"<=");
  244.             if ( numeric_args( token, moreslop ) )
  245.             {
  246.                 arg1 = number(token);
  247.                 arg2 = number(moreslop);
  248.                 i = ( arg1 < arg2 || arg1 == arg2 )? 1: 0;
  249.             }
  250.             else
  251.                 i = ( i <= 0 )? 1: 0;
  252.             sprintf( slop, "%d", i );
  253.         }
  254.         else if ( strncmp( q + 1, ">=", 2 ) == 0 )
  255.         {
  256.             i = load_and_compare(q+1,">=");
  257.             if ( numeric_args( token, moreslop ) )
  258.             {
  259.                 arg1 = number(token);
  260.                 arg2 = number(moreslop);
  261.                 i = ( arg1 > arg2 || arg1 == arg2 )? 1: 0;
  262.             }
  263.             else
  264.                 i = ( i >= 0 )? 1: 0;
  265.             sprintf( slop, "%d", i );
  266.         }
  267.         else if ( strncmp( q + 1, "<", 1 ) == 0 )
  268.         {
  269.             i = load_and_compare(q+1,"<");
  270.             if ( numeric_args( token, moreslop ) )
  271.             {
  272.                 arg1 = number(token);
  273.                 arg2 = number(moreslop);
  274.                 i = ( arg1 < arg2 )? 1: 0;
  275.             }
  276.             else
  277.                 i = ( i < 0 )? 1: 0;
  278.             sprintf( slop, "%d", i );
  279.         }
  280.         else if ( strncmp( q + 1, ">", 1 ) == 0 )
  281.         {
  282.             i = load_and_compare(q+1,">");
  283.             if ( numeric_args( token, moreslop ) )
  284.             {
  285.                 arg1 = number(token);
  286.                 arg2 = number(moreslop);
  287.                 i = ( arg1 > arg2 )? 1: 0;
  288.             }
  289.             else
  290.                 i = ( i > 0 )? 1: 0;
  291.             sprintf( slop, "%d", i );
  292.         }
  293.         else if ( strncmp( q + 1, "=", 1 ) == 0 )
  294.         {
  295.             i = load_and_compare(q+1,"=");
  296.             if ( numeric_args( token, moreslop ) )
  297.             {
  298.                 arg1 = number(token);
  299.                 arg2 = number(moreslop);
  300.                 i = ( arg1 == arg2 )? 1: 0;
  301.             }
  302.             else
  303.                 i = ( i == 0 )? 1: 0;
  304.             sprintf( slop, "%d", i );
  305.         }
  306.         else if ( strncmp( q + 1, "?", 1 ) == 0 )
  307.         {
  308.             load_and_compare(q+1,"?");  /* sets token and moreslop */
  309.             if ( strlen(token) && strlen(moreslop) )
  310.                 tkn = strstr( token, moreslop );
  311.             else
  312.                 tkn = NULL;
  313.             i = ( tkn != NULL )? 1 : 0;
  314.             sprintf( slop, "%d", i );
  315.         }
  316.         else if ( stricmp( q+1, "TRUE" ) == 0 )
  317.         {
  318.             strcpy( slop,"1");
  319.         }
  320.         else if ( stricmp( q+1, "FALSE" ) == 0 )
  321.         {
  322.             strcpy( slop,"0");
  323.         }
  324.         else if ( stricmp( q+1, "T" ) == 0 )
  325.         {
  326.             strcpy( slop,"1");
  327.         }
  328.         else if ( stricmp( q+1, "F" ) == 0 )
  329.         {
  330.             strcpy( slop,"0");
  331.         }
  332.         else
  333.         {
  334.             strcpy(slop,"1");  /* any (undefined) is 1 */
  335.         }
  336.  
  337.         /* insert macro expansion into receiving buffer */
  338.  
  339.         q = "macro buffer overflow";  /* insertion error message */
  340.         strcpy( moreslop, buffer );
  341.         if (((strlen(moreslop) + strlen(slop))) >= (MACROSIZE - 1))
  342.             crash_macro(q);
  343.         else
  344.             strcat( moreslop, slop );
  345.         if (((strlen(moreslop) + strlen(p))) >= (MACROSIZE - 1))
  346.             crash_macro(q);
  347.         else
  348.             strcat( moreslop, p );
  349.         strcpy( buffer, moreslop );
  350.  
  351.         /* clear working buffers */
  352.  
  353.         memset( moreslop, 0, MACROSIZE );
  354.         memset( slop, 0, MACROSIZE );
  355.     }
  356. }
  357.  
  358.  
  359. /* macro evaluation returns 1 or 0, or -1 if syntax error */
  360. int evaluate_macro( char *p )
  361. {
  362.     int result;
  363.  
  364.     token = malloc( MACROSIZE );
  365.     slop = malloc( MACROSIZE );
  366.     moreslop = malloc( MACROSIZE );
  367.  
  368.     if ( token == (char *)NULL || slop == (char *)NULL || moreslop == (char *)NULL )
  369.         bomb("out of memory");
  370.  
  371.     if ( setjmp( os